package com.dq.demo;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;

import java.awt.Button;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JPanel;
import javax.swing.Timer;

import com.dq.utils.PlayMusicUtil;

public class TetrisFrame extends JFrame{

	private static final int WIDTH  = 535;			//这是游戏容器的宽度
	private static final int HEIGHT = 580;			//这是游戏容器的长度
	private static final int CELL = 26;				//把游戏分为网格，网格长度为26,小方块的长度也是26
	private int dir = 2;							// 1右， -1左，2 向下。
	private Smallblock wall[][] = new Smallblock[20][10];
		
	// 所有小方块的图片	 
	public static ImageIcon T = new ImageIcon("./src/com/dq/images/T.png");
	public static ImageIcon I = new ImageIcon("./src/com/dq/images/I.png");
	public static ImageIcon J = new ImageIcon("./src/com/dq/images/J.png");
	public static ImageIcon O = new ImageIcon("./src/com/dq/images/O.png");
	public static ImageIcon S = new ImageIcon("./src/com/dq/images/S.png");
	public static ImageIcon Z = new ImageIcon("./src/com/dq/images/Z.png");
	public static ImageIcon L = new ImageIcon("./src/com/dq/images/L.png");
	public static ImageIcon background = new ImageIcon("./src/com/dq/images/tetris.png");
	public static ImageIcon go = new ImageIcon("./src/com/dq/images/go.jpg");
	
	private Bigblock currentBb =  Bigblock.createBigblock();		//当前的大方块
	private Bigblock nextBb    =  Bigblock.createBigblock();		//下一个大方块
	
	//游戏窗口Frame
	
	public TetrisFrame() {
		
	this.setTitle("俄罗斯方块--by DQ");
	ImageIcon icon = new ImageIcon("./src/com/dq/images/tetris.jpg");			//给窗口设置图标
	this.setIconImage(icon.getImage());											//给窗口设置图标
	this.setSize(WIDTH-10, HEIGHT);												//设置大小
	this.setResizable(false);													//禁止用户缩放界面
	this.setLocationRelativeTo(null);											//设置居中
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);						//设置当窗口关闭时退出程序
	//GridBagLayout tlayout = new GridBagLayout();								//网格包布局
	this.setLayout(null);
	this.setVisible(true);														//窗口可见
	
	
	TetrisPanel te = new TetrisPanel();
	this.add(te);
	
				//给游戏窗口添加一个键盘监听
				this.addKeyListener(new KeyAdapter(){ //控制方向
					
					@Override
					public void keyPressed(KeyEvent e) {
			
						int code = e.getKeyCode();
						switch(code) {
						
						case KeyEvent.VK_RIGHT:
							dir = TetrisConst.RIGHT;
							break;
							
						case KeyEvent.VK_LEFT:
							dir = TetrisConst.LEFT;
							break;
							
						case KeyEvent.VK_DOWN:
							dir = TetrisConst.DOWN;
							break;
							
						}
					}
				});
	}
	
	//这是内部类
	//俄罗斯方块游戏面板类
	class TetrisPanel extends JPanel{
		
		public TetrisPanel() {
			startGame();
				this.setSize(535,580);
				this.setLayout(null);		
			}
		
		//重写JPanel类中的paint(Graphics g) 方法.

		public void paint(Graphics g) {
			paintBackground(g);					//先画背景图片
			g.translate(15, 15);
			paintWall(g);						//再画墙
			paintCurrentBlock(g);				//画出现在的大方块
			paintNextBlock(g);					//画出下一个大方块
		}
					/* 
		 			g：画笔 g.drawImage(image,x,y,null) image:绘制的图片 x:开始绘制的横坐标 y:开始绘制的纵坐标
					super.paintComponent(g);
					g.drawImage(background.getImage(),0,0,null);	 
				    */
		
		//画背景图
		protected void paintBackground(Graphics g) {			//游戏最后面的背景图片
			g.drawImage(background.getImage(),0,0,null);
		}
		
		
		//然后画出格子，也就是墙，是一个二维数组，10行20列。
		protected void paintWall(Graphics g) {			//游戏最后面的背景图片
			int i/*列*/,j/*行*/;
			for(i=0;i<20;i++) {
				for(j=0;j<10;j++) {
					int x = j*CELL;
					int y = i*CELL;
					Smallblock ss = wall[i][j];
					if(ss == null) {
					g.drawRect(x, y, CELL, CELL);
					}
					else {
						g.drawImage(ss.getsbImage().getImage(),x,y,null);
					}
				}
			}
		}

		//画出当前的大方块
		protected void paintCurrentBlock(Graphics g){
					Smallblock[] a = currentBb.bb;
					for(Smallblock Bb:a) {
						int x = Bb.getCol() * CELL;
						int y = Bb.getRow() * CELL;
						g.drawImage(Bb.getsbImage().getImage(),x,y,null);
					}
				}
		
		//画出下一个大方块
		protected void paintNextBlock(Graphics g) {
			Smallblock[] a = nextBb.bb;
			for(Smallblock Bb:a) {
				int x = Bb.getRow() * CELL + 360;
				int y = Bb.getCol() * CELL + 80;
				g.drawImage(Bb.getsbImage().getImage(),x,y,null);
			}
		}
		
		
		//游戏的主要逻辑都在这里
		private void startGame() {
			 PlayMusicUtil.playBGM();			
			//动作监听，根据前面的键盘监听来确定dir的键值来确定大方块的移动
			new Timer(350,new ActionListener() {    		//添加一个计时器
				
				@Override
				public void actionPerformed(ActionEvent e) {
					switch(dir) {
						//大方块移动
						case TetrisConst.RIGHT:
							if(canDrop()) { 
							currentBb.rigthMove();currentBb.dropMove();
							if(outOfBounds() || coincide()) {
							currentBb.leftMove();
							}
							dir = TetrisConst.DOWN;//每次改完方向后要重置方向为下
							}else{
								IsDead();
								record();
								Destroy();
								currentBb =  nextBb;						//把下一个大方块赋给当前的大方块
								nextBb    =  Bigblock.createBigblock();		//然后再生成一个新的下一个大方块
							}
							break;
						case TetrisConst.LEFT:	
							if(canDrop()) {
							currentBb.leftMove();currentBb.dropMove();
							if(outOfBounds() || coincide()) {
								currentBb.rigthMove();
								}
							dir = TetrisConst.DOWN;//每次改完方向后要重置方向为下
							}else{
								IsDead();
								record();
								Destroy();
								currentBb =  nextBb;						//把下一个大方块赋给当前的大方块
								nextBb    =  Bigblock.createBigblock();		//然后再生成一个新的下一个大方块
							}
							break;
						case TetrisConst.DOWN:
							if(canDrop()) {
							currentBb.dropMove();
							}else{
								IsDead();
								record();
								Destroy();
								currentBb =  nextBb;						//把下一个大方块赋给当前的大方块
								nextBb    =  Bigblock.createBigblock();		//然后再生成一个新的下一个大方块
							}
							break;
					}repaint();													//每次移动之后都要重新画一遍所有东西
					}
				}).start();
			
		}
		
		//判断是否能继续往下掉
		//小方块应该有坐标，row行，col列
		public boolean canDrop() {
			Smallblock[] a = currentBb.bb;
			for(Smallblock Bb:a) {
				int x = Bb.getRow();
				int y = Bb.getCol();
				if(x==19 || wall[x + 1][y] != null){					//只要有一个小方块的行等于19或者它的下一行有小方块，就不能下掉了
					return false;
				}
		}
			return true;
	}
		
		//小方块不能下落时就把小方块存到墙的二维数组里去
		public void record() {
			Smallblock[] bb = currentBb.bb;
			for (Smallblock Bb : bb) {
				int col = Bb.getCol();
				int row = Bb.getRow();
				wall[row][col] = Bb;
			}
		}
	
		//检查小方块是否越界
		public boolean outOfBounds() {
			Smallblock[] bb = currentBb.bb;
			for (Smallblock Bb : bb) {
				int col = Bb.getCol();
				int row = Bb.getRow();
				if (col < 0 || col > 9 || row > 19 || row < 0) {
					return true;
				}
			}
			return false;
		}
		
		//检查小方块是否和其他的小方块重合
		public boolean coincide() {
			Smallblock[] bb = currentBb.bb;
			for (Smallblock Bb : bb) {
				int row = Bb.getRow();
				int col = Bb.getCol();
				if (wall[row][col] != null) {		//只要这个数组的内容不为空就说明已经有小方块了
					return true;
				}
			}
			return false;
		}
		
		
		//判断某一行是否为满
		public boolean Isfull(int row) {
			Smallblock[] bb = wall[row];
			for (Smallblock Bb : bb) {
				if (Bb == null) {
					return false;
				}
			}
			return true;
		}
		
		//消灭一行已经满了的墙
		public void Destroy() {
			Smallblock[] d = currentBb.bb;
			for(Smallblock Bb:d) {
				int row = Bb.getRow();
				while(row<20){
					if(Isfull(row)) {
						 wall[row] = new Smallblock[10];			//满了的这一行重新初始化
						 for (int i = row; i > 0; i--) {
								System.arraycopy(wall[i - 1], 0, wall[i], 0, 10);
							}
							wall[0] = new Smallblock[10];			//最顶行初始化
					}
					row++;
				}
			}
		}
		
		public void IsDead() {
			Smallblock[] a = currentBb.bb;
			for(Smallblock Bb:a) {
				int x = Bb.getRow();
				int y = Bb.getCol();
				if(x==0 && wall[x + 1][y] != null){					//只要有一个小方块的行等于0或者它的下一行有小方块，就死了。
					dir = 0;										//让大方块停止下落
					Button b = new Button("确定");
					b.setSize(50,50);
					b.setLocation(100, 100);
					JDialog dialog = new JDialog();
					dialog.setTitle("你死了，游戏结束");
					dialog.setSize(250, 250);
					dialog.setLocationRelativeTo(null);
					dialog.add(b);
					b.addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent e) {
							System.exit(0);
						}
					});
					dialog.setVisible(true);
				}
		}
		}
		
	}

}
